package studio.raptor.databus.graph.rule;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.context.annotation.Configuration;
import studio.raptor.databus.graph.domain.Event;


/**
 * 事件之间的关联关系
 * 按照接口维度存储，每个接口对应对个关联关系
 *
 * @author jack
 * @since 1.0
 */
@Configuration
public class EventRelationship {

  //key:code 接口编码，value:接口事件之间的关联关系
  private Map<String, Relationship> serviceRelationship = new ConcurrentHashMap<>(50);


  public class Relationship {

    //key:partyId,value:eventId
    public BiMap<Long, String> partyRule = HashBiMap.create();
    //key:prodId,value:eventId
    public BiMap<Long, String> prodRule = HashBiMap.create();
    //key:partyId,value:eventId
    public BiMap<Long, String> modifyPartyRule = HashBiMap.create();
    //key:accountId,value:eventId
    public Map<Long, String> accountRule = new HashMap<>();
    //key:accountId,value:eventId
    public Map<Long, String> modifyAccountRule = new HashMap<>();
    //key:offerId,value:eventId
    public Map<Long, String> offerRule = new HashMap<>();


    //key:eventId,value:[acctId]
    public SetMultimap<String, Long> accountRuleReverse = HashMultimap.create();
    //key:eventId,value:[acctId]
    public SetMultimap<String, Long> modifyAccountRuleReverse = HashMultimap.create();
    //key:eventId,value:[offerId]
    public SetMultimap<String, Long> offerRuleReverse = HashMultimap.create();

  }


  /**
   * 获取当前事件依赖的事件ID
   *
   * @param event 当前事件
   * @return 当前事件依赖的事件id集合
   */
  public Set<String> getDependEventId(Event event) {
    Relationship relationship = getRelationship(event.getCode());
    DefaultSortingRule sortingRule = new DefaultSortingRule(event, relationship);
    Set<String> dependEventIds = sortingRule.sortByProd().sortByParty().sortByModifyParty()
        .sortByAcct()
        .sortByMofifyAcct().sortByOffer()
        .getDependIds();
    if (dependEventIds.contains(event.getEventId())) {
      dependEventIds.remove(event.getEventId());
    }
    return dependEventIds;
  }

  /**
   * 根据接口编码获取接口对应的事件依赖关系
   *
   * @param code 接口编码
   * @return 如果不存在返回一个空的关系
   */
  public Relationship getRelationship(String code) {
    Objects.requireNonNull(code);
    if (serviceRelationship.containsKey(code)) {
      return serviceRelationship.get(code);
    }

    Relationship relationship = new Relationship();
    serviceRelationship.put(code, relationship);
    return relationship;

  }

  /**
   * 更新接口对应的事件依赖关系
   *
   * @param eventId 当前任务的事件id
   * @param code 接口编码
   */
  public void updateRelationship(String eventId, String code) {
    Relationship relationship = serviceRelationship.get(code);

    relationship.partyRule.inverse().remove(eventId);
    relationship.prodRule.inverse().remove(eventId);

    Set<Long> acctIds = relationship.accountRuleReverse.get(eventId);
    for (Iterator<Long> ite = acctIds.iterator(); ite.hasNext(); ) {
      relationship.accountRule.remove(ite.next());
    }
    relationship.accountRuleReverse.removeAll(eventId);

    Set<Long> offerIds = relationship.offerRuleReverse.get(eventId);
    for (Iterator<Long> ite = offerIds.iterator(); ite.hasNext(); ) {
      relationship.offerRule.remove(ite.next());
    }
    relationship.offerRuleReverse.removeAll(eventId);
  }

}
